package com.fms.sys.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fms.sys.entity.User;
import com.fms.sys.mapper.UserMapper;
import com.fms.sys.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.time.LocalDateTime;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author Jinfeng
 * @since 2023-02-24
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public Map<String, Object> login(User user) {
        log.info("尝试登录用户: {}", user.getUsername());

        // 根据用户名查询
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername, user.getUsername());
        User loginUser = this.baseMapper.selectOne(wrapper);

        if (loginUser != null) {
            log.info("[登录校验] 用户: {}，当前状态: {}", loginUser.getUsername(), loginUser.getStatus());
            // 新增：校验用户状态
            if (loginUser.getStatus() != null && loginUser.getStatus() == 0) {
                log.info("[登录校验] 用户已被禁用: {}", user.getUsername());
                throw new RuntimeException("用户已被禁用，请联系管理员");
            }
            // 如果是第一次登录，密码还是明文，则进行加密
            if (!loginUser.getPassword().startsWith("$2a$")) {
                log.info("首次登录，对密码进行加密处理");
                String rawPassword = loginUser.getPassword();
                if (rawPassword.equals(user.getPassword())) {
                    // 密码匹配，进行加密并更新
                    String encodedPassword = passwordEncoder.encode(rawPassword);
                    loginUser.setPassword(encodedPassword);
                    this.updateById(loginUser);
                    log.info("密码加密并更新成功");
                } else {
                    log.info("明文密码不匹配");
                    return null;
                }
            } else {
                // 已经是加密密码，使用BCrypt验证
                if (!passwordEncoder.matches(user.getPassword(), loginUser.getPassword())) {
                    log.info("加密密码验证失败");
                    return null;
                }
            }

            // 生成token
            String token = UUID.randomUUID().toString();
            log.info("登录成功，生成token: {}", token);

            // 创建用户信息副本，移除敏感信息
            User userInfo = new User();
            userInfo.setId(loginUser.getId());
            userInfo.setUsername(loginUser.getUsername());
            userInfo.setEmail(loginUser.getEmail());
            userInfo.setPhone(loginUser.getPhone());
            userInfo.setAvatar(loginUser.getAvatar());
            userInfo.setRole(loginUser.getRole());
            userInfo.setStatus(loginUser.getStatus());

            // 存入redis，设置30分钟过期
            redisTemplate.opsForValue().set(token, userInfo, 30, TimeUnit.MINUTES);

            // 返回数据
            Map<String, Object> data = new HashMap<>();
            data.put("token", token);
            data.put("user", userInfo);
            return data;
        }

        log.info("用户不存在: {}", user.getUsername());
        return null;
    }

    @Override
    public Map<String, Object> getUserInfo(String token) {
        log.info("获取用户信息，token: {}", token);
        // 根据token获取用户信息，从redis查询
        Object obj = redisTemplate.opsForValue().get(token);
        if (obj != null) {
            // 反序列化
            User loginUser = JSON.parseObject(JSON.toJSONString(obj), User.class);
            Map<String, Object> data = new HashMap<>();
            data.put("name", loginUser.getUsername());
            data.put("avatar", loginUser.getAvatar());
            data.put("email", loginUser.getEmail());
            data.put("role", loginUser.getRole());

            // 角色
            List<String> roleList = this.baseMapper.getRoleNameByUserId(loginUser.getId());
            data.put("roles", roleList);
            return data;
        }
        log.error("Redis中未找到token对应的用户信息: {}", token);
        return null;
    }

    @Override
    public void logout(String token) {
        // 从Redis中删除token
        redisTemplate.delete(token);
        log.info("用户登出成功，token已删除");
    }

    @Override
    public Map<String, Object> getUserStats() {
        Map<String, Object> stats = new HashMap<>();
        // 获取总用户数
        long totalUsers = this.count();
        stats.put("totalUsers", totalUsers);

        // 获取近期新增用户数（例如最近30天）
        LocalDateTime thirtyDaysAgo = LocalDateTime.now().minusDays(30);
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(User::getCreateTime, thirtyDaysAgo);
        long newUsers = this.count(wrapper);
        stats.put("newUsers", newUsers);

        return stats;
    }

    @Override
    public void updateUserStatus(Long userId, Integer status) {
        User user = new User();
        user.setId(userId);
        user.setStatus(status);
        this.updateById(user);
    }
}
